package com.zhao.dota.security.integration.authenticator.sms;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhao.dota.bo.AuthenticateUser;
import com.zhao.dota.contant.LoginConstant;
import com.zhao.dota.model.User;
import com.zhao.dota.security.integration.IntegrationAuthentication;
import com.zhao.dota.security.integration.authenticator.AbstractPreparableIntegrationAuthenticator;
import com.zhao.dota.security.integration.authenticator.sms.event.SmsAuthenticateBeforeEvent;
import com.zhao.dota.security.integration.authenticator.sms.event.SmsAuthenticateSuccessEvent;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 短信验证码集成认证
 *
 * @author LIQIU
 * @date 2018-3-31
 **/
@Component
public class SmsIntegrationAuthenticator extends AbstractPreparableIntegrationAuthenticator implements ApplicationEventPublisherAware {

    private final static String SMS_AUTH_TYPE = "sms";
    @Resource
    private PasswordEncoder passwordEncoder;
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public AuthenticateUser authenticate(IntegrationAuthentication integrationAuthentication) {
        //获取密码，实际值是验证码
        String password = integrationAuthentication.getAuthParameter("password");
        //获取用户名，实际值是手机号
        String phone = integrationAuthentication.getUsername();
        //发布事件，可以监听事件进行自动注册用户
        this.applicationEventPublisher.publishEvent(new SmsAuthenticateBeforeEvent(integrationAuthentication));

        LambdaQueryWrapper<User> query = Wrappers.lambdaQuery(User.class).eq(User::getPhone, phone);
        //通过手机号码查询用户
        User user = userService.getOne(query);
        if (user == null) {
            throw new UsernameNotFoundException(String.format("手机号[%s]未注册", integrationAuthentication.getUsername()));
        }
        //将密码设置为验证码
        //发布事件，可以监听事件进行消息通知
        AuthenticateUser authenticateUser = new AuthenticateUser();
        BeanUtils.copyProperties(user, authenticateUser);
        authenticateUser.setPassword(passwordEncoder.encode(password));
        this.applicationEventPublisher.publishEvent(new SmsAuthenticateSuccessEvent(integrationAuthentication));
        return authenticateUser;
    }

    @Override
    public void prepare(IntegrationAuthentication integrationAuthentication) {
        String smsToken = integrationAuthentication.getAuthParameter(LoginConstant.SMS_TOKEN_PARAM);
        String smsCode = integrationAuthentication.getAuthParameter(LoginConstant.PASSWORD_PARAM);
        String username = integrationAuthentication.getAuthParameter(LoginConstant.USERNAME_PARAM);
/*        todo zhq 验证码判断
        Result<Boolean> result = verificationCodeClient.validate(smsToken, smsCode, username);
        if (!result.getData()) {
            throw new OAuth2Exception("验证码错误或已过期");
        }*/
    }

    @Override
    public boolean support(IntegrationAuthentication integrationAuthentication) {
        return SMS_AUTH_TYPE.equals(integrationAuthentication.getAuthType());
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
}
